import {useState} from 'react';
import {DEFAULT_DISPLAY_NAME} from '../constants';
import {RegisterUsernameRequest, RegisterFastRequest} from '../types';
import {
  finishRegisterUsername,
  startRegisterUsername,
  startRegisterFast,
  finishRegisterFast,
  startDeletePasskey,
  finishDeletePasskey,
} from '../api/anonymous-actor-api';
import {Passkey} from 'react-native-passkey';
import {Platform} from 'react-native';
import {generateServerSig} from '../utils';

export const useRegister = function () {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const userUnregister = async (userName: string, passkeyTitle: string) => {
    if (loading) {
      return null;
    }
    setLoading(true);
    setError('');
    try {
      const response = await startDeletePasskey(userName, passkeyTitle);
      console.log('startDeletePasskey response:', response);
      if ((response as any)?.['Err']) {
        throw new Error((response as any)['Err']);
      }
      const options = JSON.parse((response as any)['Ok']).publicKey;
      const deleteRegisterResult = await Passkey.get(options).catch(() => {
        throw new Error(`Webauthn unregistration fail`);
      });

      console.log('deleteRegisterResult', deleteRegisterResult);

      const unregistReturn = await finishDeletePasskey(
        typeof deleteRegisterResult == 'string'
          ? deleteRegisterResult
          : JSON.stringify(deleteRegisterResult),
      ).catch(err => {
        throw new Error(err.message);
      });
      console.log('finishUserUnregister unregistReturn', unregistReturn);
      setLoading(false);

      if ((unregistReturn as any)?.['Err']) {
        throw new Error((unregistReturn as any)['Err']);
      }

      return userName;
    } catch (error: any) {
      setLoading(false);
      console.warn(`userUnregister() fail:`, error);
      setError(error instanceof Error ? error.message : error.toString());
      return null;
    }
  };

  const registerUsername = async (regRequest: RegisterUsernameRequest) => {
    if (loading) {
      return null;
    }
    setLoading(true);
    setError('');
    try {
      const timestamp = new Date().getTime();
      const serverSig = generateServerSig(regRequest.userName, timestamp + '');
      const response = await startRegisterUsername(
        regRequest.userName,
        regRequest.passkeyTitle,
        {
          server_sig: serverSig,
          timestamp: timestamp + '',
        },
        regRequest.displayName ?? DEFAULT_DISPLAY_NAME,
      ).catch(err => {
        throw new Error(err.message);
      });
      console.log('startRegisterUsername responseL:', response);
      if ((response as any)?.['Err']) {
        throw new Error((response as any)['Err']);
      }

      const options = JSON.parse((response as any)['Ok']).publicKey;
      const registrationResult = await Passkey.create(options).catch(error => {
        console.log('Passkey error', error);
        throw new Error(`Webauthn registration fail.`);
      });

      let passkeyResult: any = registrationResult;
      if (Platform.OS === 'android') {
        if (typeof passkeyResult == 'string') {
          passkeyResult = JSON.parse(passkeyResult);
        }
        passkeyResult['response']['transports'] = ['internal'];
      }

      console.log('startRegistration registrationResult', registrationResult);

      const registReturn = await finishRegisterUsername(
        typeof passkeyResult == 'string'
          ? (passkeyResult as string)
          : JSON.stringify(passkeyResult),
      ).catch(err => {
        throw new Error(err.message);
      });
      console.log('finishRegisterUsername registReturn', registReturn);

      setLoading(false);

      if ((registReturn as any)?.['Err']) {
        throw new Error((registReturn as any)['Err']);
      }

      if ((registReturn as any)['Ok'][0] === regRequest.userName) {
        return regRequest.userName;
      } else {
        throw new Error('Something went wrong, please try again later.');
      }
    } catch (error: any) {
      setLoading(false);
      console.warn(`registerUsername() fail:`, error);
      setError(error instanceof Error ? error.message : error.toString());
      return null;
    }
  };

  const registerFast = async (regRequest: RegisterFastRequest) => {
    if (loading) {
      return null;
    }

    setLoading(true);
    setError('');
    try {
      const response = await startRegisterFast(
        regRequest.passkeyTitle,
        regRequest.displayName ?? DEFAULT_DISPLAY_NAME,
      ).catch(err => {
        console.warn(`startRegisterFast fail: `, err);
        throw new Error(err.message);
      });
      console.log('startRegisterFast response:', response);
      if ((response as any)?.['Err']) {
        throw new Error((response as any)['Err']);
      }

      console.log('Passkey support', Passkey.isSupported());
      let options = JSON.parse((response as any)['Ok'][0]).publicKey;

      console.log('options', options);
      const registrationResult = await Passkey.create(options).catch(error => {
        console.log('Passkey error', error);
        throw new Error(`Webauthn registration fail`);
      });

      let passkeyResult: any = registrationResult;
      if (Platform.OS === 'android') {
        if (typeof passkeyResult == 'string') {
          passkeyResult = JSON.parse(passkeyResult);
        }
        passkeyResult['response']['transports'] = ['internal'];
      }

      console.log('startRegistration registrationResult:', registrationResult);
      const registReturn = await finishRegisterFast(
        typeof passkeyResult == 'string'
          ? (passkeyResult as string)
          : JSON.stringify(passkeyResult),
      ).catch(err => {
        throw new Error(err.message);
      });
      console.log('finishRegisterFast registReturn:', registReturn);
      if ((registReturn as any)?.['Err']) {
        throw new Error((registReturn as any)['Err']);
      }
      setLoading(false);
      if ((registReturn as any)['Ok'][0]) {
        return (registReturn as any)['Ok'][0];
      } else {
        throw new Error(
          'Something went wrong, please try again later. code:0003',
        );
      }
    } catch (error: any) {
      setLoading(false);
      console.warn(`registerFast fail: `, error);
      setError(error instanceof Error ? error.message : error.toString());
    }
  };

  return {
    loading,
    error,
    setError,
    registerUsername,
    userUnregister,
    registerFast,
  };
};
